/**
 * Written By: MinHo Kim (minho.kim.korea@gmail.com)
 * Copyright (C) 2011, MinHo Kim, Software Expert Program, KAIST University, Seoul, Korea.
 * This program is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published 
 * by the Free Software Foundation; version 2 of the License.
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
 * See the GNU General Public License for more details.
 */
package kaist.sep502.tsp.model;

import kaist.sep502.tsp.util.TspUtil;



/**
 * @author minho kim
 * use public members for performance, but it should be modified within this class.
 */
public class CityPath implements Cloneable, Comparable<Object> {
	public double gx = 0.0;
	public double hx = 0.0;
	public int[] tourHistory;
	public int index = 0;
//	public List<Integer> route = new ArrayList<Integer>

	/**
	 * @param departure
	 */
	public CityPath(int cityNo) {
		tourHistory = new int[Problem.getCitySize()+1];
		set(cityNo, 0.0);
	}

	/**
	 * 
	 */
	public CityPath() {
		tourHistory = new int[Problem.getCitySize()+1];
	}

	public void set(int currentCityNo, double hx){
		if(index == 0){ // 아직 초기화되지 않은 상태
			tourHistory[index++] = currentCityNo;
		} else {
			this.gx += Problem.getDistance(tourHistory[index-1], currentCityNo);
			//this.hx = hx;
			this.hx = hx;
			this.tourHistory[index++] = currentCityNo;
		}
		
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(Object o) {
		CityPath operand = (CityPath) o;
		if(this.getPathCost() > operand.getPathCost()){
			return 1;
		} else if(this.getPathCost() <= operand.getPathCost()){
			return -1;
		} else {
			return 0;
		}
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
//	@Override
//	public boolean equals(Object obj) {
//		CityPath cp = (CityPath) obj;
//		if(cp.index != this.index){
//			return false;
//		}
//		
//		if(this.parity.compareTo(cp.parity) == 0){
//			return false;
//		}
//		
////		if(this.tourHistoryParity != cp.tourHistoryParity){
////			return false;
////		}
//		
//		return true;
//	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#clone()
	 */
	@Override
	public CityPath clone(){
		CityPath clone = null;
		try {
			clone = (CityPath) super.clone();
			clone.index = this.index;
			clone.gx = this.gx;
			clone.hx = this.hx;
			
			clone.tourHistory = new int[Problem.getCitySize()+1];
			for(int i=0; i<this.index; i++){
				clone.tourHistory[i] = this.tourHistory[i];
			}
			
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return clone;
	}

	public CharSequence getPathListString() {
		StringBuilder sb = new StringBuilder();
		
		for (int i = 0; i < index; i++) {
			if (i == 0) {
				sb.append(this.tourHistory[i]);
			} else {
				sb.append("-").append(this.tourHistory[i]);
			}
		}

		return sb;
	}
	
	public int getLastCity(){
		if(this.index == 0){
			return this.tourHistory[0];
		} else {
			return this.tourHistory[this.index -1];
		}
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("[").append(getPathListString()).append("] ").append(TspUtil.formatDouble(getPathCost()));
		return sb.toString();
	}

	/**
	 * @return
	 */
	public double getPathCost() {
		return gx + hx;
	}

//	/**
//	 * @return
//	 */
//	public int[] getTourHistory() {
//		return this.tourHistory;
//	}
//
//	/**
//	 * @return
//	 */
//	public int getIndex() {
//		return this.index;
//	}

}
